using System;
using System.Collections.Generic;
using System.Linq;
using SmartSite.Network;
using static SmartSite.Common.CheckingNullArgument;
using static SmartSite.Frame.FrameTypeEnum;

namespace SmartSite.Frame
{
    /// <summary>
    /// BaseFrame
    /// <para>
    /// 实际使用帧从SubFrame派生, 不要派生自BaseFrame
    /// </para>
    /// <para>
    /// 派生帧应该设置
    /// </para>
    /// </summary>
    public class BaseFrame : IBytesBuffer, IFrameTypeKey
    {
        readonly FrameTypeEnum _Key = NullFrameType;
        public virtual FrameTypeEnum Key { get { return _Key; } }

        public List<byte> Buffer { get; }

        public int BuffertLength { get => Buffer.Count; }

        /// <summary>
        /// 协议版本. 
        /// 帧首字节高 4 bit. 当前为 4.
        /// 0-3保留,
        /// 4～15用于区分不同厂家.
        /// </summary>
        readonly IValueField<ushort> ProtocolVersionField;
        public ushort ProtocolVersion
        {
            get => ProtocolVersionField.Value;
            set => ProtocolVersionField.Value = value;
        }

        /// <summary>
        /// 厂家代码. 4 bit. ProtocolVersion 之后. 当前为 4.
        /// </summary>
        readonly IValueField<ushort> FactoryCodeField;
        public ushort FactoryCode
        {
            get => FactoryCodeField.Value;
            set => FactoryCodeField.Value = value;
        }

        /// <summary>
        /// 帧类型. 5 bit. FactoryCode 之后.
        /// </summary>
        readonly IValueField<FrameTypeEnum> FrameTypeField;
        public FrameTypeEnum FrameType
        {
            get => FrameTypeField.Value;
            set => FrameTypeField.Value = value;
        }

        /// <summary>
        /// 信息长度. 11 bit. FrameType 之后.
        /// </summary>
        protected IValueField<ushort> InfoLengthField { get; }
        public ushort InfoLength
        {
            get => InfoLengthField.Value;
            set => InfoLengthField.Value = value;
        }

        // <summary>
        /// CRC 16位检验和. 16 bit. 帧结尾.
        /// </summary>
        protected IValueField<ushort> CRCField { get; set; }
        public ushort CRC
        {
            get => CRCField.Value;
            set => CRCField.Value = value;
        }

        public BaseFrame() : this(Array.Empty<byte>()) => InitFieldValue();

        public BaseFrame(byte[] buffer)
        {
            CheckingNull(buffer, nameof(buffer));

            Buffer = buffer.ToList();
            ProtocolVersionField = new UShortField(this, 0, 4);
            FactoryCodeField = new UShortField(ProtocolVersionField, 4);
            FrameTypeField = new FrameTypeField(FactoryCodeField);
            InfoLengthField = new UShortField(FrameTypeField, 11);
            CRCField = new UShortField(InfoLengthField);
        }

        protected void InitFieldValue()
        {
            ProtocolVersion = BaseFrameDataEnum.ProtocolVersion;
            FrameTypeField.Value = _Key;
            InfoLengthField.Value = 0;
        }

        public UInt16 CalculationCRC() => Buffer.CalculationCRC(0, CRCField.Index.ToTakeUpBytes());

        public virtual void OnRestored(SocketStateEventArgs socketState) { }
    }
}